using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

using System.Collections.Generic;
using System.Data;
using System.Xml.Serialization;

using System.Text;
using System.Web.Security;

using System.Web.Script.Services;
using System.ComponentModel;
using System.Web.Configuration;

public struct Message
{
	[XmlAttribute]
	public string UserName;

	public string Text;

	public Message(string username, string text)
	{
		this.UserName = username;
		this.Text = text;
	}
}

[DataObject(true)]
public class ChatService: BasicService<Queue<Message>>
{

	static int MaxChatHistory {
		get {
			int _result;
			return Int32.TryParse(WebConfigurationManager.AppSettings["HistoryDepth"], out _result) ? _result : 25;
		}
	}
	
	protected override void MaintainCollection(Queue<Message> chat)
	{
		while(chat.Count > MaxChatHistory) {
			chat.Dequeue();
		}
	}

	[DataObjectMethod(DataObjectMethodType.Insert, true)]
	public bool WriteMessage(string messageText, Guid chatId)
	{
		if (!string.IsNullOrEmpty(messageText)) {
			chatId = Guid.Empty;

			Message _msg = new Message(Environment.CurrentUserName, messageText);

			this[chatId].Enqueue(_msg);
			return true;
		} else {
			return false;
		}
	}

	/// <summary>
	/// Retrieves all messages since the last time on and returns the
	/// messages in HTML format for direct appending to the Message label.
	/// 
	/// Uses Session to track the last time the user was on.
	/// </summary>
	/// <param name="ChatId"></param>
	/// <param name="Username"></param>
	/// <returns></returns>
	public string GetMessages(Guid chatId)
	{
		chatId = Guid.Empty;

		return string.Join("\n",
			Array.ConvertAll(
				this[chatId].ToArray(),
					new Converter<Message, string>(
						delegate(Message message)
						{
							return string.Format(@"
<span style='color:darkGray;margin-top:3px;'>{0}:</span>
<span style='padding-left:15px;'>{1}</span><br/>
		", message.UserName,
								message.Text);
						}
					)
				)
			);
	}

	[DataObjectMethod(DataObjectMethodType.Delete)]
	public void Delete(Guid id)
	{
		this[id].Clear();
	}

	/// <summary>
	/// Returns a simple HTML Link list of all users that are currently active.
	/// Users are considered active if they have posted in less than 10 minutes
	/// and 'passive' if they are just lurking. There are essentially three modes:
	/// 
	/// Active  (green image)
	/// Recently Active (orange image)
	/// Lurking  (red image)
	/// </summary>
	/// <param name="ChatId"></param>
	/// <returns></returns>
	[DataObjectMethod(DataObjectMethodType.Select, false)]
	public string[] GetActiveUsers(Guid chatId)
	{
		List<string> _chatUserList = new List<string>();

		Array.ForEach(
			this[chatId].ToArray(),
			new Action<Message>(
				delegate(Message msg)
				{
					if (!_chatUserList.Contains(msg.UserName)) {
						_chatUserList.Add(msg.UserName);
					}
				}));

		return _chatUserList.ToArray();
	}
}